/* Copyright (c) 2011 by Mani Brundha Kattamuri, Haritha Subramanyam
 *
 * Project Info:  http://code.google.com/p/andriod-travelapp-csc780/wiki/Design
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
 * USA.
 */
package com.example.TravelApp.search.common.helper;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import android.util.Log;

import com.example.TravelApp.constants.MapConstants;
import com.example.TravelApp.search.common.OverLayMapRoute;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;

/**
 * This is a helper class that contains static methods to draw path between two
 * given points Goolge Maps API is used to get route information between the two
 * locations Methods in this class are used by all the Map activities to draw
 * path
 * 
 * @author Haritha Subramanyam, Mani Brundha
 * 
 */
public class MapDrawPathHelper implements MapConstants {
	/**
	 * Constructs the URL which is used to request Google Maps for route
	 * Depending on the source and destination coordinates the URL string is
	 * constructed
	 * 
	 * @param src
	 *            - Geo points of source location
	 * @param dest
	 *            - Geo points of destination location
	 * @return - the URL to be sent to Google maps API
	 */
	private static String getGoogleMapsQueryString(GeoPoint src, GeoPoint dest) {
		// connect to map web service
		StringBuilder urlString = new StringBuilder();
		urlString.append(GOOGLE_MAPS_URL);// from
		urlString.append(Double.toString((double) src.getLatitudeE6() / 1.0E6));
		urlString.append(DELIMITER_COMMA);
		urlString
				.append(Double.toString((double) src.getLongitudeE6() / 1.0E6));
		urlString.append(GOOGLE_MAPS_URL_DEST_ADDR);// to
		urlString
				.append(Double.toString((double) dest.getLatitudeE6() / 1.0E6));
		urlString.append(DELIMITER_COMMA);
		urlString
				.append(Double.toString((double) dest.getLongitudeE6() / 1.0E6));
		urlString.append(GOOGLE_MAPS_URL_OUTPUT_SPEC);
		Log.d("xxx", "URL=" + urlString.toString());

		return urlString.toString();
	}

	/**
	 * Establishes connection with the Google Maps services It opens a
	 * connection and uses the URL constructed based on the locations
	 * 
	 * @param src
	 *            - Geo points of source location
	 * @param dest
	 *            - Geo points of destination location
	 * @return the Http URL connection
	 */
	private static HttpURLConnection getConnection(GeoPoint src, GeoPoint dest) {
		HttpURLConnection urlConnection = null;
		URL url;
		try {
			// construct maps url string
			url = new URL(getGoogleMapsQueryString(src, dest));
			urlConnection = (HttpURLConnection) url.openConnection();
			urlConnection.setRequestMethod("GET");
			urlConnection.setDoOutput(true);
			urlConnection.setDoInput(true);
			urlConnection.connect();
		} catch (MalformedURLException e) {
			Log.e("log_tag", "Error in Malformed URL" + e.toString());
		} catch (IOException e) {
			Log.e("log_tag", "Error in IO" + e.toString());
		}
		return urlConnection;
	}

	/**
	 * Draws a path from the source to the destination location Uses google maps
	 * API to get valid route; After a route is drawn the source and the
	 * destination are highlighted using map overlays. A HttpURLConnection is
	 * first made using the function getConnection
	 * 
	 * @param src
	 *            - the source location geopoint
	 * @param dest
	 *            - the destination location geopoint
	 * @param color
	 *            - color used to draw the route
	 * @param mMapView01
	 *            - the map view on which the path is drawn
	 */
	public static void drawPath(GeoPoint src, GeoPoint dest, int color,
			MapView mMapView01) {

		Document doc = null;
		HttpURLConnection urlConnection = getConnection(src, dest);
		try {

			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			doc = db.parse(urlConnection.getInputStream());

			if (doc.getElementsByTagName(GOOGLE_RESULT_GEOMETRY_ITEM)
					.getLength() > 0) {
				String path = doc
						.getElementsByTagName(GOOGLE_RESULT_GEOMETRY_ITEM)
						.item(0).getFirstChild().getFirstChild()
						.getFirstChild().getNodeValue();
				Log.d("xxx", "path=" + path);
				String[] pairs = path.split(" ");
				// lngLat[0]=longitude, lngLat[1]=latitude, lngLat[2]=height
				String[] lngLat = pairs[0].split(",");
				GeoPoint startGP = new GeoPoint(
						(int) (Double.parseDouble(lngLat[1]) * 1E6),
						(int) (Double.parseDouble(lngLat[0]) * 1E6));
				mMapView01.getOverlays().add(
						new OverLayMapRoute(startGP, startGP, 1));
				GeoPoint gp1;
				GeoPoint gp2 = startGP;
				for (int i = 1; i < pairs.length; i++) // the last one would
														// crash
				{
					lngLat = pairs[i].split(DELIMITER_COMMA);
					gp1 = gp2;
					// watch out! For GeoPoint, first:latitude, second:longitude
					gp2 = new GeoPoint(
							(int) (Double.parseDouble(lngLat[1]) * 1E6),
							(int) (Double.parseDouble(lngLat[0]) * 1E6));
					mMapView01.getOverlays().add(
							new OverLayMapRoute(gp1, gp2, 2, color));
					Log.d("xxx", "pair:" + pairs[i]);
				}
				mMapView01.getOverlays()
						.add(new OverLayMapRoute(dest, dest, 3)); // use the
																	// default
																	// color
			}
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Constructs a geoPoint out of string consisting of latitude and longitude
	 * 
	 * @param latAndLong
	 *            - the latitude and longitude string
	 * @return geoPoint - geoPoint for the given string
	 */
	public static GeoPoint getGeoPoint(String latAndLong) {
		String[] param = latAndLong.split(DELIMITER_COMMA);
		double dlong = Double.parseDouble(param[1]);
		double dlat = Double.parseDouble(param[0]);

		GeoPoint geoPoint = new GeoPoint((int) (dlat * 1E6),
				(int) (dlong * 1E6));
		return geoPoint;
	}

	/**
	 * Checks whether the latitude and longitude string is null or not
	 * 
	 * @param latAndLong
	 *            - the latitude and longitude string
	 * @return - true or false
	 */
	public static boolean isNotNull(String latAndLong) {
		if (latAndLong != "" && latAndLong != "null,null"
				&& latAndLong.equals("null,null") != true)
			return true;
		else
			return false;
	}
}
